import 'package:flutter/material.dart';

class ScaleAnimationRoute extends StatefulWidget {
  @override
  _ScaleAnimationRouteState createState() => new _ScaleAnimationRouteState();
}

//需要继承TickerProvider，如果有多个AnimationContoller，则应该使用SingleTickerProviderStateMixin
class _ScaleAnimationRouteState extends State<ScaleAnimationRoute>
    with SingleTickerProviderStateMixin {
  Animation<double> animation;
  AnimationController controller;

  @override
  void initState() {
    // TODO: implement initState

    super.initState();

    controller = new AnimationController(
        duration: const Duration(seconds: 3), vsync: this);
//使用弹性曲线
    animation = CurvedAnimation(parent: controller, curve: Curves.bounceIn);
//图片宽高从0变到300
    animation = new Tween(
      begin: 0.0,
      end: 300.0,
    ).animate(controller)
      ..addListener(() {
        //addListener函数调用了setState，所以每次动画生成一个新的数字时，当前帧都被标记为脏（dirty），这会导致Widget的build（）方法再次被调用，
        //从而在build()方法中，改变Image的宽高，因为它的高度和宽度现在使用的是animation.value，所以其会逐渐放大
        setState(() => {});
      });
    //启动动画，正向执行
    controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build

    return new Center(
      child: Image.asset(
        "imgs/avatar.png",
        width: animation.value,
        height: animation.value,
      ),
    );
  }

  @override
  void dispose() {
    // 路由销毁时需要释放动画资源
    controller.dispose();

    super.dispose();
  }
}

//AnimatedWidget封装了调用setState的细节，并允许我们将Widget分离出来
class AnimateImage extends AnimatedWidget {
  AnimateImage({Key key, Animation<double> animation})
      : super(key: key, listenable: animation);

  @override
  Widget build(BuildContext context) {
    // TODO: implement build

    final Animation<double> animation = listenable;

    return new Center(
      child: Image.asset("imgs/avatar.png",
          width: animation.value, height: animation.value),
    );
  }
}

class ScaleAnimationRoute1 extends StatefulWidget {
  @override
  _ScaleAnimationRouteState1 createState() => new _ScaleAnimationRouteState1();
}

//_ScaleAnimationRouteState1是对_ScaleAnimationRouteState的优化，build方法优化，其他不变
class _ScaleAnimationRouteState1 extends State<ScaleAnimationRoute1>
    with SingleTickerProviderStateMixin {
  Animation<double> animation;
  AnimationController controller;

  @override
  void initState() {
    // TODO: implement initState

    super.initState();

    controller = new AnimationController(
        duration: const Duration(seconds: 3), vsync: this);
//使用弹性曲线
    animation = CurvedAnimation(parent: controller, curve: Curves.bounceIn);
//图片宽高从0变到300
    animation = new Tween(
      begin: 0.0,
      end: 300.0,
    ).animate(controller);
    //启动动画，正向执行
    controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    //return AnimateImage(animation:animation,);
    //下面的代码存在一个让人疑惑的问题，即child看起来像是被指定了两次，但实际发生的事情是：将外部引用child传递给AnimatedBuilder后，
    //AnimatedBuilder再将其传递给匿名构造器，然后将该对象用作其子对象，最终的结果是将AnimatedBuilder
    //返回的对象插入到Widget树中

    /*
    这样做会带来3个好处
    1、不用显式的去添加监听器，然后在调用setState了，这个好处与AnimatedWidget是一样的
    2、动画构建的范围缩小了，如果没有builder，setState将会在父组件上下文中调用，这将会导致父组件的build方法重新调用；而有了build
    之后，则只会导致动画Widget自身的build重新调用，以避免不必要的rebuild
    3、AnimatedBuilder可以封装常见的过度效果来复用动画，
    */
    return AnimatedBuilder(
        animation: animation,
        child: Image.asset("imgs/avatar.png"),
        builder: (BuildContext context, Widget child) {
          return new Center(
            child: Container(
              width: animation.value,
              height: animation.value,
              child: child,
            ),
          );
        });
  }

  @override
  void dispose() {
    // 路由销毁时需要释放动画资源
    controller.dispose();

    super.dispose();
  }
}

class GrowTransition extends StatelessWidget {
  GrowTransition({this.child, this.animation});

  final Widget child;
  final Animation<double> animation;

  @override
  Widget build(BuildContext context) {
    return new Center(
      child: new AnimatedBuilder(
        animation: animation,
        builder: (BuildContext context, Widget child) {
          return new Container(
            height: animation.value,
            width: animation.value,
            child: child,
          );
        },
        child: child,
      ),
    );
  }
}

class ScaleAnimationRoute2 extends StatefulWidget {
  @override
  _ScaleAnimationRouteState2 createState() => new _ScaleAnimationRouteState2();
}

//_ScaleAnimationRouteState2是对_ScaleAnimationRouteState1的优化
class _ScaleAnimationRouteState2 extends State<ScaleAnimationRoute2>
    with SingleTickerProviderStateMixin {
  Animation<double> animation;
  AnimationController controller;

  @override
  void initState() {
    // TODO: implement initState

    super.initState();

    controller = new AnimationController(
        duration: const Duration(seconds: 3), vsync: this);
//使用弹性曲线
    animation = CurvedAnimation(parent: controller, curve: Curves.bounceIn);
//图片宽高从0变到300
    animation = new Tween(
      begin: 0.0,
      end: 300.0,
    ).animate(controller);
//可以通过animation.addStatusListener()方法来添加动画状态以改变监听器
/*
4中动画状态：
1、dismissed 动画在起始点停止
2、forward  动画正在正向执行
3、reverse 动画正在反向执行
4、completed 动画在终点停止
*/
    animation.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        //动画执行结束时反向执行动画
        controller.reverse();
      } else if (status == AnimationStatus.dismissed) {
        //动画恢复到初始状态是再正向执行动画
        controller.forward();
      }
    });
    //启动动画，正向执行
    controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return GrowTransition(
      child: Image.asset("imgs/avatar.png"),
      animation: animation,
    );
  }
}
